/*
 * ClasePlantilla.cpp
 *
 *  Created on: 21/05/2013
 *      Author: jonathan
 */

#include "PruebaArchivoPunteros.h"
#include "../indexado/archivos/ArchivoPunteros.h"
#include <list>
#include "../general/estructuras/Documento.h"
#include "../commons/ArchivoUtils.h"
#include "../commons/bitstream.h"
#include "../commons/Compresor.h"
#include "../commons/InfoRepositorioActual.h"
#include <fstream>
using namespace std;

void PruebaArchivoPunteros::after() {

}
void PruebaArchivoPunteros::before() {
	this->borrarArchivo("archivoPunteros");
	this->borrarArchivo("archivoPunteros2");
	this->borrarArchivo("archivoPunteros3");
	this->borrarArchivo("archivoPunteros4");
}

ResultadoTest PruebaArchivoPunteros::escribirEntrada() {
	InfoRepositorioActual::Instance()->setCantidadArchivos(2);
	ResultadoTest res("escribirEntrada");
	ArchivoPunteros punt("archivoPunteros", ios_base::out);
	list<Documento*> docs;
	Documento * doc1 = this->crearDocumento(0, 3, 1, 3, 7);
	Documento * doc2 = this->crearDocumento(1, 4, 2, 8, 23, 25);

	docs.push_back(doc1);
	docs.push_back(doc2);
	EnteroLargo b = 10;
	punt.escribir(docs, b);
	punt.close();
	//ahora chequeo q haya guardado lo q corresponde.
	BitStream bs("archivoPunteros", ios_base::in);
	Compresor com(&bs);
	EnteroLargo num = com.leerDelta();
	//no se lee el documento porque ocupa todos los docs.
	res.assertTrue(num == 3, "No se escribio bien la distancia de posiciones");
	res.assertTrue(com.leerDelta() == 2, "No se escribio bien la distancia de posiciones");
	res.assertTrue(com.leerDelta() == 2, "No se escribio bien la distancia de posiciones");
	res.assertTrue(com.leerDelta() == 4, "No se escribio bien la distancia de posiciones");

	//cant punteros
	res.assertTrue(com.leerDelta() == 4, "No se escribio bien la cant de distancias");
	res.assertTrue(com.leerDelta() == 3, "No se escribio bien la distancia de posiciones");
	res.assertTrue(com.leerDelta() == 6, "No se escribio bien la distancia de posiciones");
	res.assertTrue(com.leerDelta() == 15, "No se escribio bien la distancia de posiciones");
	res.assertTrue(com.leerDelta() == 2, "No se escribio bien la distancia de posiciones");
	delete doc1;
	delete doc2;
	return res;
}

ResultadoTest PruebaArchivoPunteros::escribirEntradaSinOmitir() {
	ResultadoTest res("escribirEntradaSinOmitir");
	ArchivoPunteros punt("archivoPunteros2", ios_base::out);
	list<Documento*> docs;
	Documento * doc1 = this->crearDocumento(1, 3, 1, 3, 7);
	Documento * doc2 = this->crearDocumento(3, 4, 2, 8, 23, 25);
	docs.push_back(doc1);
	docs.push_back(doc2);
	EnteroLargo b = 10;
	InfoRepositorioActual::Instance()->setCantidadArchivos(3);
	punt.escribir(docs, b);
	punt.close();
	//corre una posicion a la derecha +1
	//ahora chequeo q haya guardado lo q corresponde.
	BitStream bs("archivoPunteros2", ios_base::in);
	Compresor com(&bs);
	EnteroLargo i = com.leerGolomb(b) -1;
	res.assertTrue(i == 1, "No escribio bien el nro de doc");
	//distancia al 2do doc
	res.assertTrue(com.leerGolomb(b) == 2, "No escribio bien el nro de doc");

	//no se lee el documento porque ocupa todos los docs.
	bs.omitByte();
	//cant punteros
	res.assertTrue(com.leerDelta() == 3, "No se escribio bien la cant de distancias");
	res.assertTrue(com.leerDelta() == 2, "No se escribio bien la distancia de posiciones");
	res.assertTrue(com.leerDelta() == 2, "No se escribio bien la distancia de posiciones");
	res.assertTrue(com.leerDelta() == 4, "No se escribio bien la distancia de posiciones");

	//cant punteros
	res.assertTrue(com.leerDelta() == 4, "No se escribio bien la cant de distancias");
	res.assertTrue(com.leerDelta() == 3, "No se escribio bien la distancia de posiciones");
	res.assertTrue(com.leerDelta() == 6, "No se escribio bien la distancia de posiciones");
	res.assertTrue(com.leerDelta() == 15, "No se escribio bien la distancia de posiciones");
	res.assertTrue(com.leerDelta() == 2, "No se escribio bien la distancia de posiciones");
	delete doc1;
	delete doc2;
	return res;
}
ResultadoTest PruebaArchivoPunteros::leerListaPosiciones() {
	ResultadoTest res("leerListaPosiciones");
	//Armo el archivo que se va a leer.
	BitStream bs("archivoPunteros3", ios_base::out);
	//escribo dos  bytes para ignorar luego;
	bs.put(1);
	bs.put(2);
	bs.put(3);
	//escribo las lista de posiciones en Delta como haría el archivo
	Compresor com(&bs);
	//cuantas
	com.escribirDelta(2);
	//las posiciones en distancias
	//se escribe en uno corrido
	com.escribirDelta(2); //pos 1
	com.escribirDelta(3); //pos 4

	com.escribirDelta(4);
	//las posiciones en distancias
	com.escribirDelta(1); //pos 0
	com.escribirDelta(7); //pos 7
	com.escribirDelta(2); //pos 9
	com.escribirDelta(2); //pos 11
	bs.close();
	// leo las dos lista
	ArchivoPunteros arch("archivoPunteros3", ios_base::in);
	//posiciono donde terminé de escribir el relleno.
	arch.posicionar(3);

	list<EnteroLargo> * l1 = arch.leerListaPosiciones();
	list<EnteroLargo> * l2 = arch.leerListaPosiciones();

	list<EnteroLargo>::iterator it = l1->begin();
	//se escribe en uno corrido
	res.assertEquals(1, *it);
	it++;
	res.assertEquals(4, *it);
	it= l2->begin();
	res.assertEquals(0, *it);
	it++;
	res.assertEquals(7, *it);
	it++;
	res.assertEquals(9, *it);
	it++;
	res.assertEquals(11, *it);

	delete l1;
	delete l2;
	return res;
}

ResultadoTest PruebaArchivoPunteros::recuperarPosicionesProxiadas() {
	InfoRepositorioActual::Instance()->setCantidadArchivos(2);
	ResultadoTest res("recuperarPosicionesProxiadas");
	ArchivoPunteros punt("archivoPunteros4", ios_base::out);
	list<Documento*> docs;
	Documento * doc1 = this->crearDocumento(0, 3, 0, 3, 7);
	Documento * doc2 = this->crearDocumento(1, 4, 2, 8, 23, 25);

	docs.push_back(doc1);
	docs.push_back(doc2);
	EnteroLargo b = 10;
	punt.escribir(docs, b);
	punt.close();
	delete doc1;
	delete doc2;

	ArchivoPunteros puntEntrada("archivoPunteros4", ios_base::in);
    list<Documento* > * archivos = puntEntrada.leerDocumentos(0, 2, b);
    //leo al inicio del archivo.

    //Chequeo que todos los datos se recuperen bien.
    list<Documento*>::iterator it = archivos->begin();
    //El primer documento
	res.assertEquals((*it)->getNumero(),0);
	list<EnteroLargo> * posiciones= (*it)->getPosiciones();
	list<EnteroLargo>::iterator itPos = posiciones->begin();
	res.assertEquals(0,*itPos);
	itPos++;
	res.assertEquals(3,*itPos);
	itPos++;
	res.assertEquals(7,*itPos);
	delete (*it);
	it++;
	res.assertEquals((*it)->getNumero(),1);
	posiciones = (*it)->getPosiciones();

	itPos = posiciones->begin();
	res.assertEquals(2,*itPos);
	itPos++;
	res.assertEquals(8,*itPos);
	itPos++;
	res.assertEquals(23,*itPos);
	itPos++;
	res.assertEquals(25,*itPos);
	delete (*it);

    return res;
}

void PruebaArchivoPunteros::run() {
	ResultadoTest resTotal("----------------TEST_ARCHIVO_PUNTEROS------------------");
	resTotal.assertTrue(this->escribirEntrada().getResultado(), "Test1");
	resTotal.assertTrue(this->escribirEntradaSinOmitir().getResultado(), "Test2");
	resTotal.assertTrue(this->leerListaPosiciones().getResultado(), "Test3");
	resTotal.assertTrue(this->recuperarPosicionesProxiadas().getResultado(), "Test4");
	resTotal.getResultado();
}

